import { Property } from "@/core/CodeGenerator"
import { ApiMethod, Definition, OpenApi } from "@/core/OpenApi"
import { ApplyMethodsParamItem, VueCodeGenerator, VueComponent } from "@/core/VueCodeGenerator"
import { LoadingVueComponent, PageVueComponent } from "./BasePage"
import { ObjectEncoder, VueJsCodeEncoder } from "@/core/JsCodeEncoder"

class SearchFormVueComponent extends VueComponent {
	constructor(children: VueComponent[]) {
		super({
			vueComponentOptions: {
				name: 'SearchForm',
				tagName: 'search-form',
				properties: [
					new Property(':columns', "searchColumns"),
					new Property(':formData', "searchForm"),
					new Property('@search', "handleSearch"),
				]
			}, 
			vueJsCodeEncoder: new VueJsCodeEncoder()
				.addImport(`import SearchForm from '@/components/Form/SearchForm.vue'`)
				.addProperty("components", new ObjectEncoder().addSameNameProperty("SearchForm"))
				.addProperty("methods", new ObjectEncoder().addMethod("handleSearch", ['this.getTableData()'], null))
				.addMethod("data", [], new ObjectEncoder().addProperty("searchColumns", "[]").addProperty("searchForm", "{}")),
			children: children 
		})
	}

	async applyMethods(openapi: OpenApi, params: ApplyMethodsParamItem[]): Promise<void> {
		super.applyMethods(openapi, params)
		await Promise.all(params.map( async (param) => {
			if(param.name === 'listQueryApi') {
				await this.applyDefinition(openapi, param.apiMethod)
			}
		}))
	}

	applyDefinition(openapi: OpenApi, method: ApiMethod) {
		const body = openapi.findRef(method.bodyParam.schema.$ref)
		var properties = body.properties
		var searchColumns: any[] = []
		var searchForm: {[key:string]: any} = {}
		Object.keys(body.properties).forEach((key) => {
			var prop = properties[key]
			searchForm[key] = undefined
			if(prop) {
				var type = 'input'
				if(prop.enum) {
					type = 'select'
					var splits = prop.description.split(',')
					var values = splits.slice(1)
					var options = values.map((value, index) => {
						var [code, name ] = value.split(':')
						return {
							code,
							name,
							label: splits[0],
							value: prop.enum[index]
						}
					})
					searchColumns.push({
						field: key,
						label: properties[key].description,
						fieldProps: {
							placeholder: '请选择'+ properties[key].description,
							options: options
						}
					})
				} else {
					searchColumns.push({
						field: key,
						label: properties[key].description,
						fieldProps: {
							placeholder: '请输入'+ properties[key].description
						}
					})
				}
				
			}
		})
		this.vueJsCodeEncoder.addMethod("data", [], new ObjectEncoder().addProperty("searchColumns", this.stringifyWithUndefined(searchColumns).split('\n').join('\n\t')).addProperty("searchForm",  this.stringifyWithUndefined(searchForm).split('\n').join('\n\t')))
	}
}
  
class SeniorTableVueComponent extends VueComponent {
	defaultGetTableMethodStr: string
	constructor(children: VueComponent[]) {
		var defaultGetTableMethodStr = `this.loading = true
try {
\tvar res = await Controller.apiMethod({\n\t\t...this.searchForm\n\t})
\tif (res.code === 200) {
\t\tthis.tableData = (res.data || []).map((item) => {
\t\t\treturn {
\t\t\t\t...item
\t\t\t}
\t\t})
\t\tthis.$refs.seniorTable.$refs.xTable1.loadData(this.tableData)
\t}
} catch (error) {
\tconsole.log(error)
} finally {
\tthis.loading = false
}`
		super({
			vueComponentOptions: {
			name: 'Page',
			tagName: 'senior-table',
			properties: [
				new Property('ref', "seniorTable"),
				new Property(':columns', "columns"),
				new Property(':pagination', "null"),
				new Property(':border', "true"),
				new Property('@change', "getTableData"),
			]
		}, 
		children: children,
		vueJsCodeEncoder: new VueJsCodeEncoder()
			.addImport(`import SeniorTable from '@/components/SeniorPanel/SeniorTable.vue'`)
			.addProperty("components", new ObjectEncoder().addSameNameProperty('SeniorTable'))
			.addMethod("data", [], new ObjectEncoder().addProperty("columns", "[]").addProperty("tableData", "[]"))
			.addMethod("mounted", ["this.getTableData()"], null)
			.addProperty("methods", new ObjectEncoder()
				.addMethod("async getTableData", [defaultGetTableMethodStr], null))
	})

		this.defaultGetTableMethodStr = defaultGetTableMethodStr
	}
	async applyMethods(openapi: OpenApi, params: ApplyMethodsParamItem[]): Promise<void> {
		super.applyMethods(openapi, params)
		await Promise.all(params.map(async (param) => {
			if(param.name === 'listQueryApi') {
				await this.applyDefinition(openapi, param.apiMethod)
			}
		}))
	}

	applyDefinition(openapi: OpenApi, method: ApiMethod) {
		const body = openapi.findRef(method.bodyParam.schema.$ref)
		let response = openapi.findRef(method.getSchemaRef())
		if(body) {
			var values: any = []
			var properties = body.properties
			Object.keys(properties).forEach((key) => {
				values.push(`${key}: searchForm.${key}`)
			})
			var methodContent = this.defaultGetTableMethodStr.replace('Controller.apiMethod({\n\t\t...this.searchForm\n\t})', `${method.controllerName}.${method.name}({\n\t\t${values.join(',\n\t\t')}\n\t})`)
			this.vueJsCodeEncoder.addProperty("methods", new ObjectEncoder().addMethod("async getTableData", [methodContent], null))
		}
		if(response) {
			var responseBody: Definition = null
			while(response && response.refs && response.refs.length > 0) {
				responseBody = openapi.findRef(response.refs[0])
				response = responseBody
			}
			if(response) {
				var columns = []
				Object.keys(response.properties).map((key: string) => {
					var prop = response.properties[key]
					if(prop.enum) {
						var splits = prop.description.split(',')
						columns.push({
							field: key + '_desc',
							title: splits[0],
							width: 100
						})
					} else {
						columns.push({
							field: key,
							title: prop.description,
							width: 100
						})
					}
				})
				this.vueJsCodeEncoder.addMethod("data", [], new ObjectEncoder().addProperty("columns", this.stringifyWithUndefined(columns).split('\n').join('\n\t')).addProperty("tableData", "[]"))
			}
		}
	}
}

class ListQueryPageVueComponent extends PageVueComponent {
	constructor() {
		super([])
		this.title = '列表查询页面'
		this.apiMethods = [{
			title: '查询接口', 
			name: 'listQueryApi',
			controllerName: undefined,
			methodName: undefined,
			apiMethod: undefined,
			method: undefined
		}]
		this.children = [
			new LoadingVueComponent([
				new SearchFormVueComponent([]),
				new SeniorTableVueComponent([])
			])
		]
	}
}

export class ListQueryPage extends VueCodeGenerator {
	constructor() {
		super(new ListQueryPageVueComponent())
		this.title = "列表页面模板"
	}
}